import Taro from '@tarojs/taro';
import { decrypt as commonDecypt } from './secret';
import { OssConfig } from '../../types/utils/upload';

export interface UploadSignResult {
  /** AccessKeyId */
  accessId?: string;
  /** 当前服务器时间（毫秒） */
  currentTime?: number;
  /** 失效时间（毫秒） */
  expireAt?: number;
  /** Bucket的host地址 */
  host?: string;
  /** Policy表单域 */
  policy?: string;
  /** 签名信息 */
  signature?: string;
}

let formData: UploadSignResult;

//文件保存路径
let folderPath: (filePath: string) => string;
export const folderPathEvent = (cb: any) => {
  folderPath = cb;
};
//解密方法
let decrypt: (signature: string) => string;
export const decryptEvent = (cb: any) => {
  decrypt = cb;
};
// 生成文件名
const generateKey = function(filePath: string) {
  const date = new Date();
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  const path = year + (month < 10 ? '0' + month : month).toString();
  const fileKey =
    (folderPath ? folderPath(filePath) : 'default/') +
    path +
    '/' +
    new Date().getTime() +
    filePath.substring(filePath.lastIndexOf('.'));
  return fileKey;
};

const executeUpload = function(
  filePath: string,
  { host, policy, signature, accessId }: UploadSignResult = {},
  privateOss: boolean = false,
  ossConfig: OssConfig
): Promise<string> {
  const key = generateKey(filePath);
  const formData = {
    key,
    OSSAccessKeyId: accessId as string,
    policy: policy,
    signature: decrypt ? decrypt(signature!) : commonDecypt(signature!),
    success_action_status: '200'
  };
  return new Promise((resolve, reject) => {
    Taro.uploadFile({
      url: host as string,
      formData,
      filePath,
      name: 'file',
      success: function() {
        const wholePath = privateOss
          ? ossConfig.cdnS + key
          : ossConfig.cdn + key;
        resolve(wholePath);
      },
      fail: reject
    });
  });
};

const signatureVerification = function() {
  if (!formData) {
    return null;
  }
  const { expireAt } = formData;
  // 已经快过期了
  if ((expireAt as number) - Date.now() < 30 * 1000) {
    return null;
  }
  return formData;
};

/**
 * @param filePath 小程序的模板路径
 * @param everytimeSignature 是否每次都重新获取签名，默认为true
 * @param privateOss 是否是私有域上传，默认为false
 */
export const uploadToOss = function(
  filePath: string,
  securitySignApi: (params: { [key: string]: any }) => Promise<any>,
  apiData: { [key: string]: any } = {},
  ossConfig: OssConfig,
  everytimeSignature: boolean = true,
  privateOss: boolean = false
): Promise<string> {
  if (!everytimeSignature) {
    if (signatureVerification()) {
      return executeUpload(
        filePath,
        signatureVerification() as UploadSignResult,
        privateOss,
        ossConfig
      );
    }
  }
  return securitySignApi(apiData).then(res => {
    formData = res;
    return executeUpload(filePath, res, privateOss, ossConfig);
  });
};
